/*
 * @lc app=leetcode.cn id=79 lang=cpp
 *
 * [79] 单词搜索
 *
 * https://leetcode.cn/problems/word-search/description/
 *
 * algorithms
 * Medium (46.44%)
 * Likes:    1435
 * Dislikes: 0
 * Total Accepted:    365.7K
 * Total Submissions: 787.2K
 * Testcase Example:  '[["A","B","C","E"],["S","F","C","S"],["A","D","E","E"]]\n"ABCCED"'
 *
 * 给定一个 m x n 二维字符网格 board 和一个字符串单词 word 。如果 word 存在于网格中，返回 true ；否则，返回 false
 * 。
 * 
 * 单词必须按照字母顺序，通过相邻的单元格内的字母构成，其中“相邻”单元格是那些水平相邻或垂直相邻的单元格。同一个单元格内的字母不允许被重复使用。
 * 
 * 
 * 
 * 示例 1：
 * 
 * 
 * 输入：board = [["A","B","C","E"],["S","F","C","S"],["A","D","E","E"]], word =
 * "ABCCED"
 * 输出：true
 * 
 * 
 * 示例 2：
 * 
 * 
 * 输入：board = [["A","B","C","E"],["S","F","C","S"],["A","D","E","E"]], word =
 * "SEE"
 * 输出：true
 * 
 * 
 * 示例 3：
 * 
 * 
 * 输入：board = [["A","B","C","E"],["S","F","C","S"],["A","D","E","E"]], word =
 * "ABCB"
 * 输出：false
 * 
 * 
 * 
 * 
 * 提示：
 * 
 * 
 * m == board.length
 * n = board[i].length
 * 1 
 * 1 
 * board 和 word 仅由大小写英文字母组成
 * 
 * 
 * 
 * 
 * 进阶：你可以使用搜索剪枝的技术来优化解决方案，使其在 board 更大的情况下可以更快解决问题？
 * 
 */

// @lc code=start
class Solution {
public:
    bool exist(vector<vector<char>>& board, string word) {
        n = board.size();
        m = board[0].size();
        len = word.size();
        for (int i = 0; i < n; ++i) {
            for (int j = 0; j < m; ++j) {
                if (board[i][j] == word[0]) {
                    flag[i][j] = true;
                    dfs(board, word, i, j, 1);
                    flag[i][j] = false;
                }
                if (found) {
                    return true;
                }
            }
        }

        return false;
    }
private:
    void dfs(vector<vector<char>>& board, string word, int x, int y, int res)
    {
        if (found) {
            return ;
        }
        if (res == len) {
            found = true;
            return ;
        }

        for (int i = 0; i < 4; ++i) {
            int newX = x + dp[i][0];
            int newY = y + dp[i][1];
            if (newX >= 0 && newX < n && newY >= 0 && newY < m && !flag[newX][newY] && word[res] == board[newX][newY]) {
                flag[newX][newY] = true;
                dfs(board, word, newX, newY, res + 1);
                flag[newX][newY] = false;
            }
        }        
    }

    bool found;
    const int dp[4][2] = {{1, 0}, {-1, 0}, {0, 1}, {0, -1}};
    bool flag[7][7];
    int n;
    int m;
    int len;
};
// @lc code=end

